﻿using Dapper;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using static Dapper.SqlMapper;

namespace Chaunce.Dapper.Repositories
{
    /// <summary>
    /// dapper仓储层接口
    /// </summary>
    /// <typeparam name="TEntity">实体</typeparam>
    /// <typeparam name="TPrimaryKey">主键</typeparam>
    public interface IDapperRepository<TEntity, TPrimaryKey> : IDapperQueryRepository where TEntity : class
    {
        /// <summary>
        /// 根据主键获取一个实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        TEntity Get(TPrimaryKey id);

        /// <summary>
        /// 根据主键获取一个实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        Task<TEntity> GetAsync(TPrimaryKey id);


        /// <summary>
        /// 插入实体
        /// </summary>
        /// <param name="entity"></param>
        void Insert(TEntity entity);

        /// <summary>
        /// 插入实体并返回主键的值
        /// </summary>
        /// <param name="entity"></param>
        TPrimaryKey InsertAndGetId(TEntity entity);

        /// <summary>
        /// 插入实体
        /// </summary>
        /// <param name="entity"></param>
        Task InsertAsync(TEntity entity);



        /// <summary>
        /// 插入实体并返回主键的值
        /// </summary>
        /// <param name="entity"></param>
        Task<TPrimaryKey> InsertAndGetIdAsync(TEntity entity);

        int Insert<T>(string tableName, string fields, T entity);

        /// <summary>
        /// 批量插入数据，返回成功的条数（未启用事物）
        /// </summary>
        /// <typeparam name="TEntity">数据库表对应的实体类型</typeparam>
        /// <param name="tableName">数据库表名</param>
        /// <param name="fields">数据库表的所有字段，用【,】分隔（主键自增时应排除主键字段）</param>
        /// <param name="list">数据库表对应的实体集合</param>
        /// <returns>成功的条数</returns>
        int InsertBulk<T>(string tableName, string fields, List<T> list);


        /// <summary>
        /// 更新实体
        /// </summary>
        /// <param name="entity"></param>
        void Update(TEntity entity);


        /// <summary>
        /// 更新实体
        /// </summary>
        /// <param name="entity"></param>
        Task UpdateAsync(TEntity entity);


        /// <summary>
        /// 根据主键，更新唯一的一条记录
        /// </summary>
        /// <param name="connection">sql链接</param>
        /// <param name="primaryKeyName">主键字段名</param>
        /// <param name="primaryKeyValue">主键字段值</param>
        /// <param name="tableName">数据库表名</param>
        /// <param name="dicUpdate">需要更新的字段名/字段值组成的键值对</param>
        /// <returns>更新成功的记录条数</returns>
        int Update(string primaryKeyName, object primaryKeyValue, string tableName, Dictionary<string, object> dicUpdate);

        /// <summary>
        /// 删除实体
        /// </summary>
        /// <param name="entity"></param>
        void Delete(TEntity entity);

        /// <summary>
        /// 删除实体
        /// </summary>
        /// <param name="predicate">linq表达式</param>
        void Delete(Expression<Func<TEntity, bool>> predicate);

        /// <summary>
        /// 删除实体
        /// </summary>
        /// <param name="entity"></param>
        Task DeleteAsync(TEntity entity);

        /// <summary>
        /// 删除实体
        /// </summary>
        /// <param name="predicate">linq表达式</param>
        Task DeleteAsync(Expression<Func<TEntity, bool>> predicate);


        /// <summary>
        /// 根据查询条件获取一个实体
        /// </summary>
        /// <param name="predicate">linq表达式</param>
        /// <returns></returns>
        TEntity Get(Expression<Func<TEntity, bool>> predicate);

        /// <summary>
        /// 根据查询条件获取一个实体
        /// </summary>
        /// <param name="predicate">linq表达式</param>
        /// <returns></returns>
        Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> predicate);


        /// <summary>
        /// 计算总数
        /// </summary>
        /// <param name="predicate">linq表达式</param>
        /// <returns></returns>
        int Count(Expression<Func<TEntity, bool>> predicate);


        /// <summary>
        /// 计算总数
        /// </summary>
        /// <param name="predicate">linq表达式</param>
        /// <returns></returns>
        Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate);


        /// <summary>
        /// 获取集合
        /// </summary>
        /// <returns></returns>
        IList<TEntity> GetList();

        /// <summary>
        /// 获取集合
        /// </summary>
        /// <returns></returns>
        Task<IList<TEntity>> GetListAsync();


        /// <summary>
        /// 根据条件获取集合
        /// </summary>
        /// <param name="predicate">linq表达式</param>
        /// <returns></returns>
        IList<TEntity> GetList(Expression<Func<TEntity, bool>> predicate);



        /// <summary>
        /// 根据条件获取集合
        /// </summary>
        /// <param name="predicate">linq表达式</param>
        /// <returns></returns>
        Task<IList<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate);



        /// <summary>
        /// sql语句查询
        /// </summary>
        /// <param name="query">sql语句</param>
        /// <param name="parameters">参数</param>
        /// <returns></returns>
        IList<TEntity> Query(string query, object parameters = null);

        /// <summary>
        /// sql语句查询
        /// </summary>
        /// <param name="query">sql语句</param>
        /// <param name="parameters">参数</param>
        /// <returns></returns>
        Task<IList<TEntity>> QueryAsync(string query, object parameters = null);
    }
}